﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using SHomeWorkshop.LunarConcept.Controls;

namespace SHomeWorkshop.LunarConcept.Commands
{
    /// <summary>
    /// 创建时间：2011年12月27日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：保存文档命令。
    /// ★★说明：关于自定义命令的实现，可参考“NewDocument”类的备注。
    /// </summary>
    public static class SaveDocumentCommand
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// ★②，修改静态构造方法名。
        /// </summary>
        static SaveDocumentCommand()//类型构造器
        {
            //★③，修改两个字符串参数名。★④以及第三个参数的类型名。
            routedUICmd = new RoutedUICommand(
                "SaveDocumentCommand",
                "SaveDocumentCommand",
                typeof(SaveDocumentCommand),//创建RoutedUICommand对象
                null);

            routedUICmd.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control, "Ctrl + S"));

            //如果需要挂接快捷键，请参考下面这段代码：
            //routedUICmd = new RoutedUICommand(
            //    "SaveDocumentCommand",
            //    "SaveDocumentCommand",
            //    typeof(SaveDocumentCommand),//创建RoutedUICommand对象
            //    new InputGestureCollection() 
            //    { 
            //        //★⑤，修改此处三个参数，以便挂接快捷键。
            //        new KeyGesture(Key.S,ModifierKeys.Control,"Ctrl+S")
            //    });

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        #endregion

        #region 字段与属性===================================================================================================

        private static readonly string cancelSaveMessage = "　　用户取消保存操作。";
        /// <summary>
        /// [只读]用户取消操作，保存未成功，但又应视为执行完成。这是特殊情况，需要用于判断。
        /// </summary>
        public static string CancelSaveMessage
        {
            get { return SaveDocumentCommand.cancelSaveMessage; }
        }

        private static CommandBinding cmdBinding = new CommandBinding();
        /// <summary>
        /// 用在主窗口CommandBindings集合中的命令绑定。
        /// 
        /// 它的Command是RoutedUICommand。
        /// ——因此，RoutedUICommand是否可以运行将由CmdBinding的CanExecute事件决定。
        /// ——而且，RoutedUICommand的执行也是通过CmdBinding的Execute事件来进行的。
        /// </summary>
        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        private static RoutedUICommand routedUICmd;
        /// <summary>
        /// [只读静态属性]表示在WPF系统中注册的一个RoutedUICommand。
        /// ——必须和CommandBinding配合才能使用。
        ///     CommandBinding要添加到主窗口的CommandBindings集合中；
        ///     RoutedUICommand则要向WPF系统注册。
        ///     
        /// ★说明：使用静态属性是因为这样在Xaml代码中比较便于绑定。
        /// </summary>
        public static RoutedUICommand RoutedUICmd
        {
            get { return routedUICmd; }
        }

        #endregion

        #region 方法=========================================================================================================

        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //★⑧，修改此方法的实现。
            if (Globals.MainWindow.EditorManager.IsModified)
            {
                e.CanExecute = true;
            }
            else
            {
                e.CanExecute = false;
            }
        }

        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //★⑦，修改此方法的实现。
            string saveResult = Execute();

            if (saveResult == Commands.SaveDocumentCommand.CancelSaveMessage)
            {
                return;
            }
            else
            {
                LunarMessage.Warning(saveResult);
            }
        }

        /// <summary>
        /// [公开静态方法]即使此命令处于禁用状态，也可以通过代码调用此方法来执行特定任务！！！
        /// 
        /// 当被绑定的命令被调用（触发）时，会引发cmdBinding_Executed事件。
        /// 在cmdBinding_Executed事件处理器方法中已添加了调用Execute()方法的代码。
        /// 
        /// ——因此，触发命令，就相当于调用此方法！！！
        /// </summary>
        public static string Execute()
        {
            if (Globals.MainWindow == null) return "　　未找到Globals.MainWindow。";
            EditorManager manager = Globals.MainWindow.EditorManager;
            if (manager == null) return "　　未找到页面管理器。";

            if (manager.FullPathOfDiskFile != null)
            {
                //此方法会自行判断是.png/.lcpt/.lctmp
                return SaveDocumentToDiskFile(Globals.MainWindow);
            }
            else
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Title = Globals.AppName + "——保存文档：";
                sfd.Filter = Globals.DocumentName +
                    "(*." + Globals.ExtensionName + ")|*." + Globals.ExtensionName;
                sfd.FilterIndex = 0;

                string defFileName = Globals.MainWindow.EditorManager.DefaultShortFileName;
                if (defFileName != null && defFileName.Length > 0)
                {
                    sfd.FileName = defFileName;
                }

                Globals.SwitchInputMethod(true);//打开输入法。

                if (sfd.ShowDialog() == true)
                {
                    Globals.SwitchInputMethod(false);
                    Globals.MainWindow.MainScrollViewer.Focus();
                    return SaveDocumentToDiskFile(Globals.MainWindow, sfd.FileName);
                }
                else
                {
                    Globals.SwitchInputMethod(false);
                    Globals.MainWindow.MainScrollViewer.Focus();
                    return Commands.SaveDocumentCommand.CancelSaveMessage;//这个特殊处理。
                }
            }
        }

        /// <summary>
        /// ★此方法并非自定义命令类必须的方法。
        /// <param name="newFullPathOfDiskFile">如果提供此参数，即按此参数指定路径保存；
        /// 如果没有提供，则按编辑器此前指定的路径保存。</param>
        /// </summary>
        internal static string SaveDocumentToDiskFile(MainWindow win, string newFullPathOfDiskFile = null)
        {
            if (win == null) return "　　未传入主窗口。";

            System.Xml.XmlDocument doc = win.EditorManager.XmlDocument;

            string fullPathOfDiskFile;

            //SaveAs()是调用本方法并提供newFullPathOfDiskFile参数来实现的。
            if (newFullPathOfDiskFile != null)
            {
                fullPathOfDiskFile = newFullPathOfDiskFile;
            }
            else
            {
                fullPathOfDiskFile = win.EditorManager.FullPathOfDiskFile;
            }

            if (doc == null) return "　　未能根据主窗口页面管理器取后台Xml文档。";

            //刷新备注
            if (win.PageCommentEditor.IsModified && win.EditorManager != null)
            {
                win.UpdatePageCommentText(win.EditorManager.GetMainSelectedPageEditor());
            }

            if (fullPathOfDiskFile.EndsWith("." + Globals.ExtensionNameOfOutportPng))
            {
                return OutportToImageFileCommand.Execute(fullPathOfDiskFile);
            }
            else if (fullPathOfDiskFile.EndsWith("." + Globals.ExtensionNameOfTemplate))
            {
                string saveTemplateResult = OutportToImageFileCommand.Execute(fullPathOfDiskFile);

                if (saveTemplateResult == string.Empty)
                {
                    //保存好后，保持当前“win.EditorManager.fullPathOfDiskPath”一致。
                    if (newFullPathOfDiskFile != null)
                    {
                        win.EditorManager.FullPathOfDiskFile = newFullPathOfDiskFile;
                    }

                    win.EditorManager.IsModified = false;
                    win.EditorManager.ModifingItemsList.SynchronizeSavePoint();

                    RecentFileItem.WriteRecentFilesToXmlFile(win.EditorManager.FullPathOfDiskFile);
                    RecentFileItem.ReadRecentFilesFromXmlFile();
                }

                return saveTemplateResult;
            }

            try
            {
                using (System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(fullPathOfDiskFile, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    doc.WriteTo(writer);
                }

                //保存好后，保持当前“win.EditorManager.fullPathOfDiskPath”一致。
                if (newFullPathOfDiskFile != null)
                {
                    win.EditorManager.FullPathOfDiskFile = newFullPathOfDiskFile;
                }

                win.EditorManager.IsModified = false;
                win.EditorManager.ModifingItemsList.SynchronizeSavePoint();


                RecentFileItem.WriteRecentFilesToXmlFile(win.EditorManager.FullPathOfDiskFile);
                RecentFileItem.ReadRecentFilesFromXmlFile();

                return string.Empty;
            }
            catch (Exception ex)
            {
                return "保存文件时出现异常，异常信息如下：\r\n" + ex.Message + "\r\n" + ex.StackTrace;
            }
            finally
            {
                Globals.MainWindow.MainScrollViewer.Focus();
            }
        }

        #endregion
    }
}
